《Android开源库》Realm For Android~ Getting Help and Models(译文)

获得帮助

你编程时需要帮助?:在 StackOverflow 上提问。我们在实时监控并且回答 SO 上的相关问题!
要报告一个 bug?:在我们的 GitHub 仓库里新建一个问题,并且尽可能地按问题模板将 bug 描述清楚。
需要一个新功能?:在我们的 GitHub 仓库里新建一个问题,并且尽可能地按问题模板将该功能描述清楚。
想知道接下来将会发生什么?:看看我们的 changelog。这里有我们即将发布的改动以及修改历史。

模型

Realm 数据模型定义需要继承自 RealmObject 类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public class User extends RealmObject {

private String name;
private int age;

@Ignore
private int sessionId;

// Standard getters & setters generated by your IDE…
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getSessionId() { return sessionId; }
public void setSessionId(int sessionId) { this.sessionId = sessionId; }
}

Realm 数据模型不仅仅支持 private 成员变量,你还可以使用 public、protected 以及自定义的成员方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class User extends RealmObject {

public String name;

public boolean hasLongName() {
return name.length() > 7;
}

@Override
public boolean equals(Object o) {
// Custom equals comparison
}
}

字段类型

Realm 支持以下字段类型:boolean、byte、short、int、long、float、double、String、Date和byte []。整数类型 short、int 和 long 都被映射到 Realm 内的相同类型(实际上为 long )。再者,还可以使用 RealmObject 的子类和 RealmList<? extends RealmObject> 来表示模型关系。

Realm 对象中还可以声明包装类型(boxed type)属性,包括:Boolean、Byte、Short、Integer、Long、Float和Double。通过使用包装类型,可以使这些属性存取空值(null)。

@Required修饰类型和空值(null)

某些时候,空值(null)对于属性并不合适。这时可以使用注解 @Required 告诉 Realm 强制禁止空值(null)被存储。只有 Boolean、 Byte、 Short、 Integer、 Long、 Float、 Double、 String、 byte[] 以及 Date 可以被 @Required 修饰。在其它类型属性上使用 @Required 修饰会导致编译失败。基本数据类型(primitive types)不需要使用注解 @Required,因为他们本身就不可为空。RealmObject 属性永远可以为空。

忽略的属性

注解 @Ignore 意味着一个字段不应该被保存到 Realm。某些时候输入的信息包含比模型更多的字段,而你不希望处理这些未使用的数据字段,你可以用 @Ignore 来标识这些你希望被 Realm 忽略的字段

Auto-Updating Objects

RealmObject 是实时的、自动更新的底层数据的映射视图。你不需要去重新获得对象已取得其最新版本。对于数据的改动会即时反应到相关的对象或者查询结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

final Dog myDog;
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
myDog = realm.createObject(Dog.class);
myDog.setName("Fido");
myDog.setAge(1);
}
});

realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Dog myPuppy = realm.where(Dog.class).equalTo("age", 1).findFirst();
myPuppy.setAge(2);
}
});

myDog.getAge(); // => 2

RealmObject 和 RealmResults 的设计不仅仅是为了更快和更有效率,它们同时也让代码更加简洁以及反应性更强。举例来说,假设你的 Activity 或者 Fragment 依赖于某个 RealmObject 或者 RealmResults,你无需担心何时去刷新或者重新获取它们以更新 UI——它们会自动更新。

你可以通过订阅 Realm notifications 来得知 Realm 的数据在何时被更新从而刷新你的 UI。

索引(Index)属性

注解 @Index 会为字段增加搜索索引。这会导致插入速度变慢,同时数据文件体积有所增加,但能加速查询。因此建议仅在需要加速查询时才添加索引。目前仅支持索引的属性类型包括:String、byte、short、int、long、boolean和Date。

主键 (primary keys)

@PrimaryKey 可以用来定义字段为主键,该字段类型必须为字符串(String)或整数(short、int 或 long)以及它们的包装类型(Short、Int 或 Long)。不可以存在多个主键。使用支持索引的属性类型作为主键同时意味着为该字段建立索引。

当创建 Realm 对象时,所有字段会被设置为默认值。为了避免与具有相同主键的另一个对象冲突,建议创建一个 unmanaged 对象,为字段的赋值,然后用 copyToRealm() 方法将该对象复制到 Realm。

主键的存在意味着可以使用 copyToRealmOrUpdate() 方法,它会用此主键尝试寻找一个已存在的对象,如果对象存在,就更新该对象;反之,它会创建一个新的对象。当 copyToRealmOrUpdate() 的调用对象没有主键时,会抛出异常。

使用主键会对性能产生影响。创建和更新对象将会慢一点,而查询则会变快。很难量化这些性能的差异,因为性能的改变跟你数据库的大小息息相关。

Realm.createObject()会返回一个所有字段被设置为默认值的新对象。如果该模型类存在主键,那么有可能返回对象的主键的默认值与其它已存在的对象冲突。建议创建一个非托管(unmanaged)Realm 对象,并给其主键赋值,然后调用 copyToRealm() 来避免冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final MyObject obj = new MyObject();
obj.setId(42);
obj.setName("Fish");
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// This will create a new object in Realm or throw an exception if the
// object already exists (same primary key)
// realm.copyToRealm(obj);

// This will update an existing object with the same primary key
// or create a new object if an object with no primary key = 42
realm.copyToRealmOrUpdate(obj);
}
});

字符串(String)和包装类型(Short、Int 或 Long)的主键可以被赋予空值(null);除非它们同时被 @Required 修饰。

定制对象(Customizing Objects)

你几乎可以把 RealmObject 当作 POJO 使用。只需扩展 RealmObject,将相应属性声明为 public。不需要 setter 和 getter, 而是直接访问属性。

1
2
3
4
public class Dog extends RealmObject {
public String name;
public int age;
}

你可以像使用其他类一样直接使用 Dog 类。createObject() 和 copyToRealm() 可以帮助你创建一个托管给 Realm 的 Dog 对象。

1
2
3
4
5
6
7
8
realm.executeTransaction(new Realm.Transaction() {
@Overrride
public void execute(Realm realm) {
Dog dog = realm.createObject(Dog.class);
dog.name = "Fido";
dog.age = 5;
}
};

如果需要的话,你可以在 setter 和 getter 中添加你自己的逻辑。例如你可能需要在保存之前验证值的合法性。另外,你还可以为你的 RealmObject 添加自定义方法。

限制

目前不支持 final、transient 和 volatile 修饰的成员变量,这主要是为了 Realm 对象在非托管(unmanaged RealmObject)时候的行为差异化。

Realm 数据模型不可以继承自除了 RealmObject 以外的其它对象。你可以选择不声明默认无参数构造器,但是如果你声明了,那么该构造器必须为空构造器。这是目前 Realm 的一个限制。但你可以自由添加任意其它的构造器。

RealmModel 接口

除直接继承于 RealmObject 来声明 Realm 数据模型之外,还可以通过实现 RealmModel 接口并添加 @RealmClass 修饰符来声明。

1
2
3
4
5

@RealmClass
public class User implements RealmModel {

}

RealmObject 的所有方法都有其相对应的静态方法。

1
2
3
4
5
6
7
8

// With RealmObject
user.isValid();
user.addChangeListener(listener);

// With RealmModel
RealmObject.isValid(user);
RealmObject.addChangeListener(user, listener);

原文链接

https://realm.io/docs/java/latest/#getting-help
https://realm.io/docs/java/latest/#models

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×